#include "XmlType.h"
#include "string.h"
#include "stdlib.h"





XML_document_type * XML_doc_alloc(char *name)
{
	XML_document_type *doc = (XML_document_type*)malloc(sizeof(XML_document_type));
	if ( name != NULL )
		strncpy(doc->name,name, 64);
	else
		memset(doc->name, 0, 64);
	doc->root = NULL;
	doc->header = NULL;
	return doc;
}


void XML_doc_add_header(XML_tag_type *h, XML_document_type *doc)
{
	XML_tag_type *t;
	if ( doc->header == NULL )
	{
		doc->header = h;
		return;
	}
	else
	{
		for ( t = doc->header; t->next != NULL ; t = t->next )
			;
		t->next = h;
	}
}

void XML_doc_add_root(XML_tag_type *h, XML_document_type *doc)
{
	XML_tag_type *t;
	if ( doc->root == NULL )
	{
		doc->root = h;
		return;
	}
	else
	{
		for ( t = doc->root; t->next != NULL ; t = t->next )
			;
		t->next = h;
	}
}

void XML_doc_destroy(XML_document_type *doc)
{
	XML_tag_type *t;
	t = doc->header;
	while (t != NULL)
	{
		doc->header = t->next;
		XML_tag_destroy(t);
		t = doc->header;
	}
	t = doc->root;
	while (t != NULL)
	{
		doc->root = t->next;
		XML_tag_destroy(t);
		t = doc->root;
	}
	free(doc);	
}







XML_tag_type * XML_tag_alloc( char *name )
{
XML_tag_type *t;
		
	t = (XML_tag_type*)malloc(sizeof (XML_tag_type));

	t->dataP = NULL;

	if ( name == NULL )
		memset(t->name,0,64);
	else
		strncpy(t->name, name, 64);

	memset(t->data,0,256);
	t->firstChild = NULL;
	t->firstAtt = NULL;
	t->next = NULL;	
	t->type = enTagNull;
	t->numChildren = 0;
	return t;
}

void XML_tag_destroy(XML_tag_type *t)
{
XML_tag_type *c;
XML_attribute_type *att;

	if( t->dataP != NULL )
		free( t->dataP );

	while( t->firstChild != NULL ){
		c = t->firstChild;
		t->firstChild = t->firstChild->next;

		XML_tag_destroy( c );
	}

/*
	tmp = t->firstChild;
	while ( tmp != NULL )
	{
		tmp = tmp->next;
		XML_tag_destroy(t->firstChild);
		t->firstChild = tmp;		
	}
*/

	
	while( t->firstAtt != NULL ){
		att = t->firstAtt;
		t->firstAtt = t->firstAtt->next;
		XML_att_destroy( att );
	}

/*
	att = t->firstAtt;
	while ( att != NULL )
	{
		att = att->next;
		XML_att_destroy(t->firstAtt);
		t->firstAtt = att;
	}
*/


	free (t);
}



/*********  XML_tag_set_data  **********
* @Description	:  Sets the data of a XML tag
* 
* @Param  XML_tag_type *t :  the tag
* @Param  char data[256] :  the data
* @Return  void  :  
*****************************************/
void XML_tag_set_data(XML_tag_type *t, char data[256])
{
	if ( t == NULL ) return;
	strncpy(t->data,data,256);

}


/**** tag_insert_att ****/
/*!
 * Inserts an XML_attribute_type into the XML_tag_type
 *
 * @param t : the XML_tag_type
 * @param *att : the XML_attribute_type
 *
 * @return void  : 
 */
void XML_tag_insert_att(XML_tag_type * t, XML_attribute_type *att)
{
	XML_attribute_type *tmp = t->firstAtt;
	if ( tmp == NULL )
	{
		t->firstAtt = att;
		return ;
	}
	while ( tmp->next != NULL )
		tmp = tmp->next;
	tmp->next = att;	
}


/**** XML_tag_delete_att ****/
/*!
 * removes an XML_attribute_type from a XML_tag_type
 *
 * @param *t : the XML_tag_type
 * @param attName[64] : the XML_attribute_type's name
 *
 * @return int  : 1 - removed
			0 - not removed
 */
int XML_tag_delete_att(XML_tag_type *t, char attName[64])
{
	XML_attribute_type *att = t->firstAtt;
	XML_attribute_type *pAtt = NULL;
	while ( att != NULL )
	{
		if ( strcmp(att->name, attName) == 0 )
		{
			// found:
			if ( pAtt == NULL )
			{// delete the first att:
				t->firstAtt = att->next;
				XML_att_destroy(att);
				return 1;
			}
			else 
			{
				pAtt->next = att->next;
				XML_att_destroy(att);
				return 1;
			}
		}
		att = att->next;
	}
	return 0;
}




/**** XML_tag_add_child ****/
/*!
 * inserts a child to the parent tag
 *
 * @param *parent : the parent tag
 * @param child : the new tag to add
 * @param atIndex : location in the list of childs
 *
 * @return void  : 
 */
void XML_tag_add_child(XML_tag_type *parent, XML_tag_type* child, int atIndex)
{
	int i;
	XML_tag_type *t;
	parent->numChildren++;
	parent->type = enTagParent;
	if ( parent->firstChild == NULL )
	{
		parent->firstChild = child;
		return;
	}
	else 
	{
		if ( atIndex == 0 )
		{
			child->next = parent->firstChild ;
			parent->firstChild = child;
			return;
		}
		// not at head of the list
		for ( t = parent->firstChild , i = 1 ; i < atIndex && t->next != NULL; i++, t = t->next)
			;
		child->next = t->next;
		t->next = child;
		return;
	}
}

void XML_tag_delete_child(XML_tag_type *parent, int childIndex)
{
	int i;
	XML_tag_type *t = parent->firstChild;
	XML_tag_type *pt = NULL;

	if ( childIndex == 0 )
	{
		parent->firstChild = t->next;
		XML_tag_destroy(t);
		parent->numChildren--;
		if ( parent->firstChild == NULL )
			parent->type = enTagStandalone;
		return;
	}
	for ( i = 1, pt = t, t = t->next; i < childIndex && t != NULL ; pt = t, t = t->next )
		;
	pt->next = t->next; 
	XML_tag_destroy(t);	
	parent->numChildren--;
}



XML_attribute_type * XML_att_alloc(const char *name, const char *value)
{
	XML_attribute_type *att = (XML_attribute_type*)(malloc(sizeof (XML_attribute_type)));
	strncpy(att->name, name, 64);
	strncpy(att->value, value, 64);
	att->next = NULL;
	return att;
}

void XML_att_destroy(XML_attribute_type *att)
{
	free (att);
}


XML_tagPointer_type  *XML_tagPointer_alloc()
{
	XML_tagPointer_type *tp;
	tp = (XML_tagPointer_type *)malloc(sizeof(XML_tagPointer_type ));
	tp->next = NULL;
	tp->t = NULL;
	return tp;
}